package com.kznnc.data_structure.structure.queueStructure;

/**
 * @Description 数组队列
 * 队列的特点:
 * FIFO先进先出
 * 队尾只能进行入队操作
 * 队头只能进行出队操作
 * 队列有一个头,一个尾
 * 注意点:
 * 临界(边界问题):原有的事物有一个相对的范围,上线,限制;当到达这个边界,限制的条件或者值等 就是临界点,这个条件就是临界条件;
 * 在化一个框的时候一定要考虑临界问题;让所有的操作都能在这个框内;
 * 队列的临界问题: 当出队的时候,队列中的元素都为空的时候;
 * 当入队的时候,队列中的元素达到上限,满了的时候;
 * 队列什么时候满?  队列为减去队列的头 == 数组的长度的时候(存在假溢出)  并且 tail节点是数组的最后一个点的时候;
 * 队列什么时候空?  队尾减队头 == 0
 * @Author houchenkai
 * @Created Date: 2021/4/6 19:54
 * @ClassName
 */
public class ArrayQueue {

    private Integer[] data = null;

    private int head = 0;

    private int tail = 0;

    public ArrayQueue(int capacity) {
        this.data = new Integer[capacity];
    }

    /**
     * 入队 需注入队列满的临界问题
     *
     * @param num
     */
    public void push(Integer num) {
        // tail -head >= data.length && tail == data.length
        if (head == 0 && tail == data.length) {
            throw new RuntimeException("队列溢出");
        }
        // 队列前移
        if (tail == data.length) {
            Integer[] newData = new Integer[data.length];
            int j = 0;
            for (int i = head; i < tail; i++) {
                newData[j++] = data[i];
            }
            tail = j;
            head = 0;
            data = newData;
        }
        data[tail++] =num;
    }

    /**
     * 出队
     * @return
     */
    public Integer take() {
        if (head ==tail){
            throw new RuntimeException("队列为空");
        }
        return data[head++];
    }

    public void printerData(){
        for (int i = head; i <tail ; i++) {
            System.out.println("第"+(i+1)+"位数:"+data[i]);
        }
    }
    public static void main(String[] args) {
        ArrayQueue arrayQueue = new ArrayQueue(5);
        for (int i = 0; i < 5; i++) {
            arrayQueue.push(i);
        }
        for (int i = 0; i < 4; i++) {
            Integer take = arrayQueue.take();
            System.out.println("take==="+take);
        }
        arrayQueue.push(5);
        arrayQueue.printerData();

    }
}
